package com.adxon.data;

import com.adxon.MsgException;
import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.appengine.api.datastore.Query.SortDirection;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.fileupload.util.Streams;

public class Bits extends Ratee implements Refee{
	public final static String BSK="i5";

	public static PreparedQuery query(int limit){
		Query q=new Query(BSK).addSort("tc",SortDirection.DESCENDING);
		return DatastoreServiceFactory.getDatastoreService().prepare(q);
	}

	private String		ba;		// Extension
	private int			bc;		// length of blob
	protected byte[]	bd;		// std
	protected byte[]	bo;		// blob
	protected byte[]	bt;		// thumb
	protected byte[]	bm;		// small
	private int			rc;		// ref count

	public Bits(){
		bsk=BSK;
	}
	@Override
	public void addRef(){
		rc++;
		tm=0;
	}
	public void commit()throws MsgException{
		if(tm==0){
			byte[] s=bo;
			if(bo!=null){
				bc=bo.length;
				Bits m=findSame();
				if(m!=null){
					super.setAll(m);
					rc=m.rc+1;
					bo=null;	// don't need to save
				}
			}
			super.commit();
			bo=s;
		}
	}
	@Override
	protected void commitExt()throws MsgException{
		super.commitExt();
		if(commit("bo",bo)){
			commit("ba",ba);
			commit("bc",bc);
		}
		commit("bd",bd);
		commit("bm",bm);
		commit("bt",bt);
		commit("rc",rc);
	}
	private Bits findSame()throws MsgException{
		Filter f=new FilterPredicate("bc",FilterOperator.EQUAL,bc);
		Query q=new Query(BSK).setFilter(f);
		PreparedQuery p=DatastoreServiceFactory.getDatastoreService().prepare(q);
		for(Entity e:p.asIterable()){
			Bits r=(Bits)new Bits();
			r.update(e);
			byte[] b=r.getBits();
			for(int i=bc;--i>=0;)
				if(b[i]!=bo[i])
					continue;
			return r;
		}
		return null;
	}
	public byte[] getBits(){
		return getBits("bo",bo);
	}
	public byte[] getBits(String type)throws MsgException{
		return null;
	}
	protected byte[] getBits(String name,byte[] var){
		if(var==null){
			Blob b=updateBlob(name);
			if(b!=null)
				return b.getBytes();
		}
		return var;
	}
	public String getContentType() {
		return ba;
	}
	public long getLength(){
		return bc;
	}
	@Override
	public int getRefCount(){
		return rc;
	}
	@Override
	public void release(){
		rc--;
		tm=0;
	}
	public void setBits(byte[] bytes){
		bo=bytes;
		rc=1;
	}
	public void setBits(InputStream stream) throws IOException{
		ByteArrayOutputStream o=new ByteArrayOutputStream();
		Streams.copy(stream,o,true);
		setBits(o.toByteArray());
	}
	public void setContentType(String type) {
		ba=type;
	}
	@Override
	public Bits update()throws MsgException{
		super.update();
		ba=updateString("ba");
		rc=updateInt("rc");
		return this;
	}
}